3904. Smallest Stable Index II
- 題目描述
- 解答
Description
You are given an integer array nums of length n and an integer k.
For each index i, define its instability score as max(nums[0..i]) - min(nums[i..n - 1]).
In other words:
max(nums[0..i])is the largest value among the elements from index 0 to indexi.min(nums[i..n - 1])is the smallest value among the elements from indexito indexn - 1.
An index i is called stable if its instability score is less than or equal to k.
Return the smallest stable index. If no such index exists, return -1.
Example 1:
Input: nums = [5,0,1,4], k = 3
Output: 3
Explanation:
- At index 0: The maximum in
[5]is 5, and the minimum in[5, 0, 1, 4]is 0, so the instability score is5 - 0 = 5. - At index 1: The maximum in
[5, 0]is 5, and the minimum in[0, 1, 4]is 0, so the instability score is5 - 0 = 5. - At index 2: The maximum in
[5, 0, 1]is 5, and the minimum in[1, 4]is 1, so the instability score is5 - 1 = 4. - At index 3: The maximum in
[5, 0, 1, 4]is 5, and the minimum in[4]is 4, so the instability score is5 - 4 = 1. - This is the first index with an instability score less than or equal to
k = 3. Thus, the answer is 3.
Example 2:
Input: nums = [3,2,1], k = 1
Output: -1
Explanation:
- At index 0, the instability score is
3 - 1 = 2. - At index 1, the instability score is
3 - 1 = 2. - At index 2, the instability score is
3 - 1 = 2. - None of these values is less than or equal to
k = 1, so the answer is -1.
Example 3:
Input: nums = [0], k = 0
Output: 0
Explanation:
At index 0, the instability score is 0 - 0 = 0, which is less than or equal to k = 0. Therefore, the answer is 0.
Constraints:
1 <= nums.length <= 10^50 <= nums[i] <= 10^90 <= k <= 10^9
Solution
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var firstStableIndex = function (nums, k) {
const n = nums.length;
const suffixMin = new Array(n);
suffixMin[n - 1] = nums[n - 1];
for (let i = n - 2; i >= 0; i--) {
suffixMin[i] = Math.min(nums[i], suffixMin[i + 1]);
}
let maximum = 0;
for (let i = 0; i < n; i++) {
maximum = Math.max(maximum, nums[i]);
if (maximum - suffixMin[i] <= k) {
return i;
}
}
return -1;
};
解題思路
呈上題 3903. Smallest Stable Index I 的解題思路,若直接用同做法會因為測資較大而超時。
上題的解法是每次都重新計算 maximum 和 minimum,故要提升效率可以從此著手改善。
原本做法
/**
* @param {number[]} nums
* @param {number} k
* @return {number}
*/
var firstStableIndex = function (nums, k) {
for (let i = 0; i < nums.length; i++) {
const maximum = Math.max(...nums.slice(0, i + 1));
const minimum = Math.min(...nums.slice(i));
if (maximum - minimum <= k) return i;
}
return -1;
};
首先要改的是 maximum 的部分。
目前是每次都重新計算,但可以用一個變數儲存目前最大值,當遇到更大的數時就更新這個值。
let maximum = 0;
for (let i = 0; i < n; i++) {
maximum = Math.max(maximum, nums[i]);
}
至於 minimum,可以先建立一個陣列 suffixMin,用來儲存「從目前 index 到最右邊」的最小值。
因為 suffixMin[i] 的計算方式是:
suffixMin[i] = Math.min(nums[i], suffixMin[i + 1]);
也就是說,suffixMin[i] 的計算需要先知道右邊的 suffixMin[i + 1]。
因此我們必須先從最右邊開始計算,再一路往左建立 suffixMin。
接著才能依序計算 suffixMin[n - 2]、suffixMin[n - 3]……直到 suffixMin[0]。
如果從左到右計算,就會發現當我們要計算 suffixMin[i] 時,右邊的 suffixMin[i + 1] 還沒有被計算出來,因此無法使用這個公式。
const n = nums.length;
const suffixMin = new Array(n); // 直接建立一個長度為 n 的陣列
suffixMin[n - 1] = nums[n - 1]; // 最右邊的 suffixMin[n - 1] 沒有右邊的元素,所以它的最小值就是自己
// 從右往左建立 suffixMin
for (let i = n - 2; i >= 0; i--) {
suffixMin[i] = Math.min(nums[i], suffixMin[i + 1]); // 當前數字和右邊的最小值比較,取較小的
}
所以整體的邏輯就是先算好所有的 minimum,再從左往右算 maximum。
最後才能計算:
maximum - suffixMin[i];
也就是題目要求的:左邊最大值 - 右邊最小值
心得
豪難,看了好久才稍微理解:(